
\section{均分纸牌(p1031)}

\subsection{题目描述}

有N堆纸牌，编号分别为 1,2,…,N。每堆上有若干张，但纸牌总数必为N的倍数。可以在任一堆上取若干张纸牌，然后移动。

移牌规则为：在编号为1堆上取的纸牌，只能移到编号为222的堆上；在编号为NNN的堆上取的纸牌，只能移到编号为N−1的堆上；其他堆上取的纸牌，可以移到相邻左边或右边的堆上。

现在要求找出一种移动方法，用最少的移动次数使每堆上纸牌数都一样多。

例如N=4，4堆纸牌数分别为：

①9②8③17④6

移动3次可达到目的：

从 ③ 取4张牌放到 ④ （9,8,13,10）-> 从 ③ 取3张牌放到 ②（9,11,10,10）-> 从 ② 取1张牌放到①（10,10,10,10）。

\subsection{输入格式}

两行 \\
第一行为：N（N 堆纸牌，1≤N≤100）\\
第二行为：A1,A2,…,An（N堆纸牌，每堆纸牌初始数，1≤Ai≤10000）

\subsection{输出格式}

一行：即所有堆均达到相等时的最少移动次数。
\subsection{输入输出样例}
\textbf{输入样例}
\begin{lstlisting}
4
9 8 17 6
\end{lstlisting}

\textbf{输出样例}
\begin{lstlisting}
3
\end{lstlisting}

\subsection{分析}
如果两堆相邻纸牌之间需要移动，那么最多只需要移动一次。如果你的算法可能会移动两次，那么一定是错误的。

首先，把全部纸牌尽量平均分为两组，如果这两组之间需要移动，那么就把靠近分割线的两队之间一次移动到位。
例如，$9,8,17,6$这四个数字分为两组，前面两组的和为17，后面两组的和为23，需要移动。从17这一组去3张
纸牌，放到8这一组中去。移动之后变成$9,11,14,6$。前面两组的和为20，后面两组的和也为20。下面两组再分，
然后移动。这种二分移动方法，可以避免不必要的移牌。


\subsection{代码}
\begin{lstlisting}
#include <stdio.h>

#define N 1000

int a[N]; 
int n; 
int total; 
int avg; 

#define _pl()  printf("line=%d, i=%d, a[i]=%d, l=%d, r=%d, m=%d, should=%d, fact=%d, ret=%d\n", \
	__LINE__, i, a[i], l, r, m, should_be, in_fact, ret)

/* 
   Those two ranges are [l, mid) and [mid, r). One move is needed 
   exactly If it is imbalance between them, so we do the movement. 
*/ 
int move(int l, int r)
{
	int i=0, m=0, ret=0; 
	int diff, should_be=0, in_fact=0; 
	_pl(); 
	if (r-l<=1) {
		return ret; 
	}
	m = (l+r)/2; 
	should_be = 0; 
	in_fact = 0; 

	for(i=l; i<m; i++) {
		should_be += avg; 
		in_fact += a[i]; 
	}
	if (should_be==in_fact) {
		ret = 0; 
	} else {
		diff = should_be - in_fact; 
		a[m-1] += diff; 
		a[m] -= diff; 
		ret = 1; 
	}
	ret += move(l, m); 
	ret += move(m, r); 

	return ret; 
}

int main()
{
	int i, mv; 
	scanf("%d", &n);  
	for (i=0; i<n; i++) {
		scanf("%d", a+i); 
		total += a[i]; 
	}
	avg = total/n; 
	mv = move(0, n); 
	printf("%d\n", mv); 
	return 0; 
}
\end{lstlisting}

